package com.zengdada.authority.config.listener;

import com.alibaba.druid.pool.DruidAbstractDataSource;
import com.zengdada.authority.config.listener.jobs.ClearContainerJob;
import com.zengdada.authority.config.listener.jobs.DefaultClearContainerJob;
import com.zengdada.authority.config.quartz.JobAndTriggerManager;
import com.zengdada.authority.model.Application;
import com.zengdada.authority.service.ApplicationAuthorityService;
import com.zengdada.authority.service.impl.PublicSqlService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import org.springframework.web.context.WebApplicationContext;

import javax.servlet.ServletContext;
import javax.sql.DataSource;
import java.net.URI;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @Auther: 12614
 * @Contact: 1261438511@qq.com
 * @Date: 2018/11/20 15:39
 * @Description: 应用启动成功
 */
@Component
@Slf4j
public class ApplicationReadyEventListener implements ApplicationListener<ApplicationReadyEvent> {

    @Autowired
    @Qualifier("applicationAuthorityServiceImpl")
    private ApplicationAuthorityService applicationAuthorityService;
    @Autowired
    private PublicSqlService publicSqlService;

    @Value("${authority.application.id}")
    private String applicationId;

    @Autowired
    DataSource dataSource;

    private static JobAndTriggerManager jobAndTriggerManager;
    private static ConfigurableApplicationContext applicationContext;
    private static String TEMPLATE_CRON = "%s %s %s %s %s ? *";
    public static String CONTENT_KEY = "Content-Key";
    public static String JOB_NAME = "Job-Name";
    /**
     * 项目通用容器 (保存跨类数据)
     */
    protected final static Map<String, Object> PROJECT_CONTAINER = new HashMap<>();
    /**
     * 项目所在目录
     */
    protected static String ROOT_PATH = "";
    /**
     * 项目配置文件信息
     */
    protected static Environment ENVIRONMENT_CONFIG = null;

    public static ConfigurableApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 更具id取出容器中的数据
     *
     * @param key
     * @return
     */
    public static Object getContainerContent(String key) {
        return PROJECT_CONTAINER.get(key);
    }

    public String getApplicationId() {
        return applicationId;
    }

    /**
     * 向容器中添加临时数据
     *
     * @param key      数据名 相同数据名会覆盖
     * @param obj      数据
     * @param duration 保留时长 s
     * @param job      清除数据时回调方法
     * @throws Exception
     */
    public static <T extends ClearContainerJob> void addTempContent(String key, Object obj, int duration, T job) throws Exception {
        duration = Math.max(duration, 60);
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.SECOND, duration);
        String cron = String.format(TEMPLATE_CRON, cal.get(Calendar.SECOND), cal.get(Calendar.MINUTE), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.DATE), cal.get(Calendar.MONTH) + 1);
        // 创建定时任务到期自动清除
        String jobClassName = job != null ? job.getClass().getName() : DefaultClearContainerJob.class.getName();
        String jobName = jobClassName + String.valueOf(Math.random()).substring(3, 10);
        jobAndTriggerManager.addJob(jobClassName, jobName, "System.authority", cron, new HashMap<String, Object>() {{
            put("Content-Key", key);
            put("Job-Name", jobName);
        }});
        PROJECT_CONTAINER.put(key, obj);
    }

    /**
     * 向容器中添加“永久”数据 此永久非彼永久
     *
     * @param key
     * @param obj
     * @throws Exception
     */
    public static void addPermanentContent(String key, Object obj) throws Exception {
        PROJECT_CONTAINER.put(key, obj);
    }

    /**
     * 删除容器内容
     *
     * @param key
     */
    public static void removeContainerContent(String key) {
        try {
            PROJECT_CONTAINER.remove(key);
        } catch (Exception e) {
            log.error("删除“{}”容器内容失败：{}", key, e.getMessage());
        }
    }


    public static String getRootPath() {
        return ROOT_PATH;
    }

    public static String getProperty(String key) {
        return ENVIRONMENT_CONFIG.getProperty(key);
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        log.info("-----服务器启动了-----");
        applicationContext = event.getApplicationContext();
        WebApplicationContext webApplicationContext = (WebApplicationContext) applicationContext;
        ServletContext servletContext = webApplicationContext.getServletContext();
        ENVIRONMENT_CONFIG = applicationContext.getEnvironment();
        jobAndTriggerManager = (JobAndTriggerManager) applicationContext.getBeanFactory().getBean("jobAndTriggerManager");
//        try { //测试临时容器
//            ApplicationReadyEventListener.addTempContent("lalal", 1, 70, null);
//            ApplicationReadyEventListener.addTempContent("lalal1", 1, 60, null);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        try {
            URI uri = ResourceUtils.getURL("classpath:").toURI();
            String path = uri.getPath();
            if (null == path) {
                path = uri.toString().replace("jar:file:", "");
            }
            String servletContextContextPath = servletContext.getContextPath();
            if (!StringUtils.isBlank(servletContextContextPath)) {
                ROOT_PATH = path.substring(0, path.indexOf(servletContextContextPath.substring(1)));
            } else {
                ROOT_PATH = path;
            }
        } catch (Exception e) {
//            e.printStackTrace();
            log.error("项目根目录获取失败,非war包形式启动请把 server.servlet.context-path 配置为和项目目录相同");
            applicationContext.close();
        }

        // 初始一些配置
        // 获取项目id
        Application application = applicationAuthorityService.selectById(applicationId);
        if (application == null) {
            log.error("项目配置错误 请配置有效的软件ID(authority.application.id)");
            applicationContext.close();
            return;
        }
        Properties properties = new Properties();
        properties.put("authority.application.name", application.getName());
        //  添加配置
        ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) ENVIRONMENT_CONFIG;
        configurableEnvironment.getPropertySources().addLast(new PropertiesPropertySource("init-after-configure", properties));

        if (((DruidAbstractDataSource) dataSource).getDriverClassName().contains("oracle")) {
            // 获取Oracle版本
            Map<String, Object> oracleVersionMap = publicSqlService.selectOneBySQL("select version from product_component_version");
            String version = (String) oracleVersionMap.getOrDefault("version", "0.0.0");
            double oracleVersion = Double.valueOf(version.substring(0, version.indexOf(".", version.indexOf(".") + 1)));
            properties.put("oracle.version.str", version);
            properties.put("oracle.version.num", oracleVersion);
        }

//        // 定时更新权限信息
//        try {
//            jobAndTriggerManager.addJob("com.zengdada.authority.config.listener.jobs.UpdatePowerMapJob", "UpdatePowerMapJob", "System.authority", "0 0 */1 * * ? *", null);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }
}
